package io.jjz.dao;

import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.util.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Author       : 蒋俊钊 80256973
 * Date         : 2019/12/20
 * Copyright    (C) ChinaMerchantsBank
 */
@Repository
public class AdminDao {
    private static final Logger LOGGER = LoggerFactory.getLogger(AdminDao.class);

    @Resource
    private Connection connection;

    /**
     * 创建表
     *
     * @param tableName 表名称
     * @param families  列族
     */
    public boolean createTable(String tableName, String... families) throws IOException {
        try (Admin admin = connection.getAdmin()) {
            TableName table = TableName.valueOf(tableName);
            if (admin.tableExists(table)) {
                LOGGER.info("Table:[{}] Exists", tableName);
                return false;
            }

            HTableDescriptor tableDescriptor = new HTableDescriptor(table);
            for (String family : families) {
                tableDescriptor.addFamily(new HColumnDescriptor(family));
            }
            admin.createTable(tableDescriptor);
            LOGGER.info("Create table:[{}] Successfully!", tableName);
        }
        return true;
    }

    /**
     * 删除表
     */
    public boolean deleteTable(String tableName) throws IOException {
        try (Admin admin = connection.getAdmin()) {
            TableName table = TableName.valueOf(tableName);
            if (!admin.tableExists(table)) {
                LOGGER.info("Table: [{}] is not existed.", tableName);
                return true;
            }
            // 删除前要先禁用
            admin.disableTable(table);
            admin.deleteTable(table);
            LOGGER.info("delete table:[{}] successfully!", tableName);
            return true;
        }
    }

    /**
     * 禁用表
     */
    public void disableTable(String tableName) throws IOException {
        try (Admin admin = connection.getAdmin()) {
            TableName table = TableName.valueOf(tableName);
            admin.disableTable(table);
        }
    }


    /**
     * 判定表是否存在
     */
    public boolean existsTable(String tableName) throws IOException {
        try (Admin admin = connection.getAdmin()) {
            TableName table = TableName.valueOf(tableName);
            return admin.tableExists(table);
        }
    }

    /**
     * 判断表的rowkey是否存在空洞区间
     */
    public boolean isAllCover(String tableName) throws IOException, DeserializationException {
        try (Table table = connection.getTable(TableName.valueOf("hbase:meta"))) {
            Scan scan = new Scan().setRowPrefixFilter(tableName.getBytes())
                    .addColumn("info".getBytes(), "regioninfo".getBytes());
            ResultScanner scanner = table.getScanner(scan);
            byte[] r = new byte[]{};
            for (Result result : scanner) {
                byte[] bytes = result.getValue("info".getBytes(), "regioninfo".getBytes());
                HRegionInfo hRegionInfo = HRegionInfo.parseFrom(bytes);
                xor(r, hRegionInfo.getStartKey());
                xor(r, hRegionInfo.getEndKey());
            }
            return Bytes.toStringBinary(r).equals("");
        }
    }

    private void xor(byte[] a, byte[] b) {
        int length = a.length > b.length ? a.length : b.length;
        //Arrays.fill(a, length - a.length);
        for (int i = 0; i < length; i++) {
            a[i] ^= b[i];
        }
    }
}
